package io.bd;

import io.Archivo;
import io.Carpeta;
import io.Cliente;
import io.ItemAgenda;
import io.ItemBusqueda;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;

/**
 *
 * @author Mariano Zapata
 */
public class GestorBD {
    
    private Connection conexion;
    private Control control;
    private ABMRCliente abmrCliente;
    private ABMRCarpeta abmrCarpeta;
    private ABMRArchivo abmrArchivo;
    private ABMRAgenda abmrAgenda;
    
    private static final String DRIVER= "org.h2.Driver";
    private static final String BD= "jdbc:h2:ej_dat;IFEXISTS=TRUE";
    private static final String USUARIO= "zapamariano";
    private static final String CONTRASENIA= "4s1mpmlt";
    
    public GestorBD()
    {
        conexion= null;
        abmrCliente= null;
        abmrCarpeta= null;
        abmrArchivo= null;
        abmrAgenda= null;
        control= new Control();
    }
    
    public void conectar() throws ClassNotFoundException, SQLException
    {
        Class.forName(DRIVER);
        conexion= DriverManager.getConnection(BD, USUARIO, CONTRASENIA);
        conexion.setAutoCommit(false);
        abmrCliente= new ABMRCliente(conexion);
        abmrCarpeta= new ABMRCarpeta(conexion);
        abmrArchivo= new ABMRArchivo(conexion);
        abmrAgenda= new ABMRAgenda(conexion);
    }
    
    public void desconectar() throws SQLException
    {
        conexion.rollback();
        conexion.close();
    }
    
    public void expandirCarpeta(Carpeta carpeta) throws SQLException
    {
        abmrCarpeta.recuperar(carpeta, abmrCliente, abmrArchivo);
        abmrCliente.recuperar(carpeta);
        abmrArchivo.recuperar(carpeta);
    }
    
    public Cliente abrirCliente(Cliente c, int duenio) throws SQLException, IOException
    {
        c.setDuenio(duenio);
        if (control.estaAbierto(c))
            return null;
        else
        {
            abmrCliente.cargar(c);
            Cliente aux= new Cliente(c.obtenerCopiaRuta()); //PARA NO TENER ALMACENADO UN CLIENTE CON TODOS LOS DATOS.
            aux.setDuenio(duenio);
            control.abrirCliente(aux);
            return c;
        }
    }
    
    public void cerrarCliente(Cliente c) {control.cerrarCliente(c);}
    
    public void cerrarTodos(int duenio) {control.cerrarTodos(duenio);}
    
    public Object [] crearCliente(Cliente c, Carpeta padre, int duenio) throws SQLException
    {
        Object [] ret= new Object[2];
        Cliente nuevo= abmrCliente.crear(c, padre);
        conexion.commit();
        Cliente aux= new Cliente(nuevo.obtenerCopiaRuta());
        aux.setDuenio(duenio);
        control.abrirCliente(aux);
        this.expandirCarpeta(padre);
        ret[0]= padre;
        ret[1]= nuevo;
        return ret;
    }
    
    public Carpeta guardarCliente(Cliente c) throws SQLException
    {
        abmrCliente.guardar(c);
        conexion.commit();
        List<Long> rutaPadre= c.obtenerCopiaRuta();
        int ultimo= rutaPadre.size() - 1;
        rutaPadre.remove(ultimo);
        Carpeta padre= abmrCarpeta.obtenerCarpeta(rutaPadre);
        this.expandirCarpeta(padre);
        return padre;
    }
    
    public boolean eliminarCliente(Cliente c, int quienElimina) throws SQLException
    {
        c.setDuenio(quienElimina);
        if (!control.estaAbiertoPorOtro(c))
        {
            abmrCliente.eliminar(c);
            conexion.commit();
            control.cerrarCliente(c);
            return true;
        }
        else
            return false;
    }
    
    public Carpeta cortarCliente(Cliente c, Carpeta nuevoPadre, int quienCorta) throws SQLException
    {
        c.setDuenio(quienCorta);
        if (!control.estaAbiertoPorOtro(c))
        {
            abmrCliente.cortar(c, nuevoPadre);
            conexion.commit();
            this.expandirCarpeta(nuevoPadre);
            return nuevoPadre;
        }
        else
            return null;
    }
    
    public Carpeta copiarCliente(Cliente c, Carpeta nuevoPadre, int quienCopia) throws SQLException, IOException
    {
        c.setDuenio(quienCopia);
        if (!control.estaAbiertoPorOtro(c))
        {
            abmrCliente.copiar(c, nuevoPadre);
            conexion.commit();
            this.expandirCarpeta(nuevoPadre);
            return nuevoPadre;
        }
        else
            return null;
    }
    
    public Carpeta crearCarpeta(Carpeta c, Carpeta padre) throws SQLException
    {
        abmrCarpeta.crear(c, padre);
        conexion.commit();
        this.expandirCarpeta(padre);
        return padre;
    }
    
    public Carpeta guardarCarpeta(Carpeta c, Carpeta padre) throws SQLException
    {
        abmrCarpeta.guardar(c);
        conexion.commit();
        this.expandirCarpeta(padre);
        return padre;
    }
    
    public boolean eliminarCarpeta(Carpeta c, int quienElimina) throws SQLException
    {
        if (control.esEliminable(c, quienElimina))
        {
            abmrCarpeta.eliminar(c, abmrCliente, abmrArchivo);
            conexion.commit();
            return true;
        }
        else
            return false;
    }
    
    public Carpeta cortarCarpeta(Carpeta c, Carpeta nuevoPadre, int quienCorta) throws SQLException
    {
        if (control.esEliminable(c, quienCorta))
        {
            abmrCarpeta.cortar(c, nuevoPadre);
            conexion.commit();
            this.expandirCarpeta(nuevoPadre);
            return nuevoPadre;
        }
        else
            return null;
    }
    
    public Carpeta copiarCarpeta(Carpeta c, Carpeta nuevoPadre, int quienCopia) throws SQLException, IOException
    {
        if (control.esEliminable(c, quienCopia))
        {
            abmrCarpeta.copiar(c, nuevoPadre, abmrCliente, abmrArchivo);
            conexion.commit();
            this.expandirCarpeta(nuevoPadre);
            return nuevoPadre;
        }
        else
            return null;
    }
    
    public Carpeta crearArchivo(Archivo a, Carpeta padre, InputStream is) throws SQLException
    {
        abmrArchivo.crear(a, padre, is);
        conexion.commit();
        this.expandirCarpeta(padre);
        return padre;
    }
    
    public InputStream obtenerBytes(Archivo a, int duenio) throws SQLException
    {
        a.setDuenio(duenio);
        if (!control.estaAbierto(a))
        {
            InputStream ret= abmrArchivo.obtenerBytes(a);
            Archivo aux= new Archivo(a.obtenerCopiaRuta());
            aux.setDuenio(duenio);
            control.abrirArchivo(aux);
            return ret;
        }
        else
            return null;
    }
    
    public Carpeta cambiarNombreArchivo(Archivo a, Carpeta padre, int duenio) throws SQLException
    {
        a.setDuenio(duenio);
        if (!control.estaAbiertoPorOtro(a))
        {
            abmrArchivo.cambiarNombre(a);
            conexion.commit();
            this.expandirCarpeta(padre);
            return padre;
        }
        else
            return null;
    }
    
    public void cerrarArchivo(Archivo a, boolean guardar, InputStream is) throws SQLException
    {
        control.cerrarArchivo(a);
        if (guardar)
            abmrArchivo.guardarBytes(a, is);
    }
    
    public boolean eliminarArchivo(Archivo a, int duenio) throws SQLException
    {
        a.setDuenio(duenio);
        if (!control.estaAbiertoPorOtro(a))
        {
            abmrArchivo.eliminar(a);
            conexion.commit();
            control.cerrarArchivo(a);
            return true;
        }
        else
            return false;
    }
    
    public Carpeta cortarArchivo(Archivo a, Carpeta nuevoPadre, int quienCorta) throws SQLException
    {
        a.setDuenio(quienCorta);
        if (!control.estaAbiertoPorOtro(a))
        {
            abmrArchivo.cortar(a, nuevoPadre);
            conexion.commit();
            this.expandirCarpeta(nuevoPadre);
            return nuevoPadre;
        }
        else
            return null;
    }
    
    public Carpeta copiarArchivo(Archivo a, Carpeta nuevoPadre, int quienCopia) throws SQLException
    {
        a.setDuenio(quienCopia);
        if (!control.estaAbiertoPorOtro(a))
        {
            abmrArchivo.copiar(a, nuevoPadre);
            conexion.commit();
            this.expandirCarpeta(nuevoPadre);
            return nuevoPadre;
        }
        else
            return null;
    }
    
    public List<ItemAgenda> obtenerItemsAgenda(String fecha) throws SQLException {
        return abmrAgenda.recuperar(fecha);
    }
    
    public List<ItemAgenda> crearItemAgenda(ItemAgenda item) throws SQLException
    {
        abmrAgenda.crear(item);
        conexion.commit();
        return abmrAgenda.recuperar(item.getFecha());
    }
    
    public boolean eliminarItemAgenda(ItemAgenda item) throws SQLException
    {
        abmrAgenda.eliminar(item);
        conexion.commit();
        return true;
    }
    
    public List<ItemAgenda> modificarItemAgenda(ItemAgenda item) throws SQLException
    {
        if (abmrAgenda.existe(item))
            abmrAgenda.modificar(item);
        else
            abmrAgenda.crear(item);
        conexion.commit();
        return abmrAgenda.recuperar(item.getFecha());
    }
    
    public List<ItemBusqueda> buscarCarpeta(String palabraClave) throws SQLException {
        return abmrCarpeta.buscarCarpeta(palabraClave);
    }
    
    public List<ItemBusqueda> buscarArchivo(String palabraClave) throws SQLException {
        return abmrCarpeta.buscarArchivo(palabraClave);
    }
    
    public List<ItemBusqueda> buscarClienteApellido(String palabraClave) throws SQLException {
        return abmrCarpeta.buscarClienteApellido(palabraClave);
    }
    
    public List<ItemBusqueda> buscarClienteNombre(String palabraClave) throws SQLException {
        return abmrCarpeta.buscarClienteNombre(palabraClave);
    }
    
    public List<ItemBusqueda> buscarClienteDni(String palabraClave) throws SQLException {
        return abmrCarpeta.buscarClienteDni(palabraClave);
    }
}
